//
//  IMDisplayList.swift
//  ActorSDK
//
//  Created by 孙继刚 on 16/2/26.
//  Copyright © 2016年 Madordie. All rights reserved.
//

import UIKit

public enum IMListChangeType {
    case Added
    case Removed
    case Moved
    case Updated
    
    case Other
}

// 为了简化使用的业务逻辑，为了防止ActorSDK内部整体架构逻辑对原SDK造成影响。特封装此类进行隔离ARDisplayList的影响
public class IMDisplayList: NSObject, ARDisplayList_AppleChangeListener, ARDisplayList_Listener {

    public enum ListenerType {
        case Default
        case Apple
    }
    
    public let bindObj: AnyObject!
    public let section: Int!
    public var displayList: ARDisplayList!
    public var listenerType: ListenerType!
    public let callBack: (bindObj: AnyObject!, displayList: IMDisplayList, changeType: IMListChangeType!, fromIndexPaths: [NSIndexPath]?, toIndexPaths: [NSIndexPath]?) -> Void!
    public var formatItem: ((item: AnyObject) -> [String: AnyObject])?
    
    init(bindObj: AnyObject!, displayList: ARDisplayList!, listenerType: ListenerType = .Default, section: Int = 0, changeNotifa: (bindObj: AnyObject!, displayList: IMDisplayList, ChangeType: IMListChangeType!, fromIndexPaths: [NSIndexPath]?, toIndexPaths: [NSIndexPath]?) -> Void) {
        self.bindObj = bindObj
        self.callBack = changeNotifa
        self.section = section
        self.displayList = displayList
        
        self.listenerType = listenerType
    }
    /**
     开始监听
     */
    public func startListen() {
        switch listenerType! {
        case .Default:
            displayList.addListener(self)
        case .Apple:
            displayList.addAppleListener(self)
        }
    }
    /**
     结束监听
     */
    public func stopLinsten() {
        switch listenerType! {
        case .Default:
            displayList.removeListener(self)
        case .Apple:
            displayList.removeAppleListener(self)
        }
    }
//    public func getProcessedList() -> AAPreprocessedList? {
//        return displayList.getProcessedList() as? AAPreprocessedList
//    }
    /**
     取出对应IndexPath的数据
        //  如果返回nil说明无数据或者section错误!!!
     - parameter indexPath: indexPath description
     
     - returns: return value description
     */
    public func itemWithIndex(indexPath: NSIndexPath) -> [String: AnyObject]? {
        var item: AnyObject?
        if indexPath.section == section {
            item = displayList.itemWithIndex(jint(indexPath.row))
        }
        
        guard item != nil else { return nil }
        if formatItem == nil {
            return ["No Format Item": item!]
        } else {
            return formatItem!(item: item!)
        }
    }
    /**
     对当前 section计数
     
     - parameter section: section
     
     - returns:  总数
     */
    public func count(section: Int = 0) -> Int {
        return Int(displayList.size())
    }
    
    //  MARK: - ARDisplayList_AppleChangeListener
    public func onCollectionChangedWithChanges(modification: ARAppleListUpdate!) {
        
        if modification.nonUpdateCount() > 0 {
            // Removed rows
            if modification.removedCount() > 0 {
                var rows = [NSIndexPath]()
                for i in 0 ..< modification.removedCount() {
                    rows.append(NSIndexPath(forRow: Int(modification.getRemoved(jint(i))), inSection: section))
                }
                callBack(bindObj: bindObj, displayList: self, changeType: .Removed, fromIndexPaths: nil, toIndexPaths: rows)
            }
            
            // Added rows
            if modification.addedCount() > 0 {
                var rows = [NSIndexPath]()
                for i in 0..<modification.addedCount() {
                    rows.append(NSIndexPath(forRow: Int(modification.getAdded(jint(i))), inSection: section))
                }
                callBack(bindObj: bindObj, displayList: self, changeType: .Added, fromIndexPaths: nil, toIndexPaths: rows)
            }
            
            // Moved rows
            if modification.movedCount() > 0 {
                for i in 0..<modification.movedCount() {
                    let mov = modification.getMoved(jint(i))
                    callBack(bindObj: bindObj, displayList: self, changeType: .Moved, fromIndexPaths: [NSIndexPath(forRow: Int(mov.getSourceIndex()), inSection: section)], toIndexPaths: [NSIndexPath(forRow: Int(mov.getDestIndex()), inSection: section)])
                }
            }
        }
        
        var updated = [Int]()
        var updatedForce = [Int]()
        
        //  根据消息列表改的，如果崩了重新找
        let list = self.displayList.getProcessedList() as? AAPreprocessedList
        if modification.updatedCount() > 0 {
            for i in 0..<modification.updatedCount() {
                
                let updIndex = Int(modification.getUpdated(i))
                // Is forced update not marking as required for soft update
                if (list!.forceUpdated[updIndex]) {
                    continue
                }
                updated.append(updIndex)
            }
        }
        
        if list != nil {
            for i in 0..<list!.forceUpdated.count {
                if list!.forceUpdated[i] {
                    updatedForce.append(i)
                }
            }
            for i in 0..<list!.updated.count {
                if list!.updated[i] {
                    // If already in list
                    if updated.contains(i) {
                        continue
                    }
                    updated.append(i)
                }
            }
        }
        
        for rows in [updated, updatedForce] {
            var updateRows = [NSIndexPath]()
            for i in rows {
                updateRows.append(NSIndexPath(forRow: i, inSection: section))
            }
            callBack(bindObj: bindObj, displayList: self, changeType: .Updated, fromIndexPaths: nil, toIndexPaths: updateRows)
        }
    }
    
    //  MARK: - ARDisplayList_Listener
    public func onCollectionChanged() {
        callBack(bindObj: bindObj, displayList: self, changeType: .Other, fromIndexPaths: nil, toIndexPaths: nil)
    }
}
